package avicit.bdp.dms.das.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.service.dto.BdpTableDTO;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.CheckParaUtils;
import avicit.bdp.common.utils.enums.StatusEnums;
import avicit.bdp.core.enums.DataStateEnum;
import avicit.bdp.core.enums.TableTypeEnum;
import avicit.bdp.dms.das.dao.BdpDasCategoryDao;
import avicit.bdp.dms.das.dto.BdpDasCategoryDTO;
import avicit.bdp.dms.das.dto.BusinessDTO;
import avicit.bdp.dms.perm.dto.CategoryPermDTO;
import avicit.bdp.dms.perm.utils.common.PermCommonService;
import avicit.platform6.api.system.SysLookupClient;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.context.ThreadContextHelper;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import avicit.platform6.core.rest.msg.QueryRespBean;
import com.github.pagehelper.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @金航数码科技有限责任公司
 * @作者：developer
 * @邮箱：developer@avic-digital.com
 * @创建时间： 2020-06-24 14:53
 * @类说明：bdp_das_categoryService
 * @修改记录：
 */
@Transactional
@Service
public class BdpDasCategoryService extends BaseService<BdpDasCategoryDao, BdpDasCategoryDTO> {
    private static final Logger LOGGER = LoggerFactory.getLogger(BdpDasCategoryService.class);

    @Autowired
    private BdpDasTableService bdpDasTableService;

    @Autowired
    private BdpDasCategoryDao bdpDasCategoryDao;

    @Autowired
    private BusinessService businessService;

    /**
     * 权限公共服务Service
     */
    @Autowired
    private PermCommonService commonService;

    /**
     * V6平台通用代码
     */
    @Autowired
    private SysLookupClient sysLookupClient;

    /**
     * 新增对象
     *
     * @param bdpDasCategoryDTO 保存对象
     * @return String
     */
    @Transactional
    public String insertBdpDasCategory(BdpDasCategoryDTO bdpDasCategoryDTO) {
        try {
            if (StringUtils.isBlank(bdpDasCategoryDTO.getParentId())) {
                bdpDasCategoryDTO.setParentId("0");
            }
            checkNameUnique(bdpDasCategoryDTO);
            checkCodeUnique(bdpDasCategoryDTO);
            CheckParaUtils.checkIntegerValidity(bdpDasCategoryDTO.getOrderBy(), logger, "排序号必填");

            if (bdpDasCategoryDTO.getType() == 1 && StringUtils.isNotBlank(bdpDasCategoryDTO.getParentId())) {
                if (checkData(bdpDasCategoryDTO.getParentId())) {
                    throw new BusinessException("新增失败，该主题下已经存在数据，不可新增子节点");
                }
                BdpDasCategoryDTO parent = this.selectByPrimaryKey(bdpDasCategoryDTO.getParentId());
                parent.setLeaf(0);
                this.updateByPrimaryKey(parent);
            }
            // step1:持久化
            bdpDasCategoryDTO.setId(ComUtil.getId());
            bdpDasCategoryDTO.setStatus(StatusEnums.STOP.getCode());
            bdpDasCategoryDTO.setLeaf(1);
            insertSelective(bdpDasCategoryDTO);

            // step2:记录日志
            BdpLogUtil.log4Insert(bdpDasCategoryDTO);

            return bdpDasCategoryDTO.getId();
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    private boolean checkData(String parentId) {
        BdpTableDTO bdpTableDTO = new BdpTableDTO();
        bdpTableDTO.setTypeId(parentId);
        List<BdpTableDTO> tables = bdpDasTableService.selectList(bdpTableDTO);

        BusinessDTO businessDTO = new BusinessDTO();
        businessDTO.setCategoryId(parentId);
        List<BusinessDTO> businessList = businessService.selectList(businessDTO);
        if (CollectionUtils.isNotEmpty(tables) || CollectionUtils.isNotEmpty(businessList)) {
            return true;
        }
        return false;
    }

    /**
     * 修改对象全部字段
     *
     * @param bdpDasCategoryDTO 修改对象
     * @return int
     */
    @Transactional
    public void updateBdpDasCategory(BdpDasCategoryDTO bdpDasCategoryDTO) {
        try {
            if (StringUtils.isBlank(bdpDasCategoryDTO.getParentId())) {
                bdpDasCategoryDTO.setParentId("0");
            }
            updateByPrimaryKey(getUpdateDto(bdpDasCategoryDTO));   //发送消息

        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 按主键单条删除
     *
     * @param id 主键id
     * @return int
     */
    @Transactional
    public void deleteBdpDasCategoryById(String id) {
        if (StringUtils.isEmpty(id)) {
            throw new BusinessException("删除失败！传入的参数主键为null");
        }
        try {
            //记录日志
            BdpDasCategoryDTO bdpDasCategoryDTO = selectByPrimaryKey(id);
            if (bdpDasCategoryDTO == null) {
                throw new BusinessException("删除失败！对象不存在");
            }
            //判断主题域下面是否有主题
            if (bdpDasCategoryDTO.getType() == 0) {
                BdpDasCategoryDTO childQuery = new BdpDasCategoryDTO();
                childQuery.setParentId(id);
                List<BdpDasCategoryDTO> child = selectList(childQuery);
                if (child != null && child.size() > 0) {
                    throw new BusinessException("删除失败！该主题域有子节点");
                }
            } else {//主题
                if (bdpDasCategoryDTO.getLeaf() == 0) {//非末级节点不可以删除
                    throw new BusinessException("删除失败！该主题有子节点");
                } else {
                    if (checkData(id)) {
                        throw new BusinessException("删除失败！该主题下已经存在数据");
                    }
                }
            }

            BdpLogUtil.log4Delete(bdpDasCategoryDTO);
            //删除业务数据
            deleteByPrimaryKey(id);

            //判断此数据的父节点是否只有此一条数据，如果是  父级节点变为末级节点
            BdpDasCategoryDTO childQuery = new BdpDasCategoryDTO();
            childQuery.setParentId(bdpDasCategoryDTO.getParentId());
            List<BdpDasCategoryDTO> child = selectList(childQuery);
            if (child == null || child.size() == 0) {
                BdpDasCategoryDTO parent = selectByPrimaryKey(bdpDasCategoryDTO.getParentId());
                parent.setLeaf(1);
                updateByPrimaryKey(parent);
            }

            // 删除所有与nodeId有关的权限设置信息
            this.commonService.deleteCategoryPerm(bdpDasCategoryDTO.getId());
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }
    }

    /**
     * 获取模型分类树
     * 注意：
     * 1、授权界面中，授权角色获取模型分类树(全部节点)，包括指定角色的权限信息
     *
     * @param roleId
     * @param keyWords 检索关键字
     * @return
     */
    @Transactional(readOnly = true)
    public List<BdpDasCategoryDTO> getAllCategory(String roleId, String keyWords) {
        if (StringUtils.isBlank(roleId)) {
            throw new BusinessException("角色ID为空.");
        }
        // 文档密级
        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();

        // step1:获取树中节点
        List<BdpDasCategoryDTO> allNodeList = Lists.newArrayList();
        if (StringUtils.isNotBlank(keyWords)) {
            // 关键字检索，需要自行拼接树结构；
            List<String> nodeIdList = this.mapper.getCategoryListByCond(keyWords, wordSecretList);
            allNodeList = getComleteNodeListInner(nodeIdList);
        } else {
            // 非关键字检索，获取整棵树
            allNodeList = this.bdpDasCategoryDao.getCategoryListWithoutPerm(StatusEnums.RUNNING.getCode(), wordSecretList);
        }

        // step2:非关键字检索，根据角色分别进行处理
        List<CategoryPermDTO> permList = this.commonService.getCategoryGrantedPermList(roleId);

        // step3:构建模型分类树
        List<BdpDasCategoryDTO> rootNodeList = new ArrayList<>();
        buildCategoryTree(allNodeList, rootNodeList, new HashMap<>());

        // step4:设置分类节点权限值
        setNodeGrantedPerm(allNodeList, permList);

        // step5:根节点特殊处理，保证任何角色都能看到根节点
        if (CollectionUtils.isEmpty(rootNodeList)) {
            BdpDasCategoryDTO rootNode = this.mapper.findCategoryRootNode();
            rootNodeList.add(rootNode);
        }

        return rootNodeList;
    }

    /**
     * 数据存储管理-数据查看，获取模型表
     * 注意：
     * 1、数据存储管理-数据查看，获取模型表，projectId实际无效，前端未传入
     * 2、仅关心数据查看权限
     *
     * @param projectId 项目空间ID
     */
    @Transactional(readOnly = true)
    public List<BdpDasCategoryDTO> findCategoryAndTableList(String projectId) {
        try {
            List<BdpDasCategoryDTO> dataList = new ArrayList<>();

            List<String> roleIdList = this.commonService.getRoleListByUserId(ThreadContextHelper.getUserId());
            List<BdpDasCategoryDTO> categoryList = findCategoryListOwnedDataViewPerm(roleIdList);
            Page<BdpTableDTO> tableQueryRet = bdpDasTableService.qureyTableListWithDataViewPerm(roleIdList,
                    TableTypeEnum.TABLE_PHYSICAL.getCode(),
                    "0", 1, null, null, null);
            List<BdpTableDTO> tableList = tableQueryRet.getResult();
            if (tableList != null && tableList.size() > 0) {
                //如果是有项目id 需要过滤到被导入过的
                if (StringUtils.isNotBlank(projectId)) {
                    List<BdpTableDTO> projectTableList = bdpDasTableService.selectListByProjectId(projectId);

                    if (projectTableList != null && projectTableList.size() > 0) {
                        //tableList.removeAll(projectTableList);
                        Map<String, Object> tableMap = Maps.newHashMap();
                        List<BdpTableDTO> delList = Lists.newArrayList();
                        for (BdpTableDTO dasTableDTO : projectTableList) {
                            tableMap.put(dasTableDTO.getId(), dasTableDTO);
                        }
                        for (BdpTableDTO dasTableDTO : tableList) {
                            if (tableMap.containsKey(dasTableDTO.getId())) {
                                delList.add(dasTableDTO);
                            }
                        }
                        tableList.removeAll(delList);
                    }
                }
                for (BdpTableDTO dasTableDTO : tableList) {
                    BdpDasCategoryDTO tableDto = new BdpDasCategoryDTO();
                    tableDto.setParentId(dasTableDTO.getTypeId());
                    tableDto.setId(dasTableDTO.getId());
                    tableDto.setName(dasTableDTO.getName());
                    tableDto.setTableFlag(1);
                    tableDto.setStoreStatus(dasTableDTO.getStoreStatus());
                    dataList.add(tableDto);
                }
            }

            Map<String, List<BdpDasCategoryDTO>> typeTableMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(dataList)) {
                for (BdpDasCategoryDTO categoryDTO : dataList) {
                    if (categoryDTO == null || StringUtils.isBlank(categoryDTO.getParentId())) {
                        continue;
                    }

                    if (!typeTableMap.containsKey(categoryDTO.getParentId())) {
                        List<BdpDasCategoryDTO> child = new ArrayList<>();
                        child.add(categoryDTO);
                        typeTableMap.put(categoryDTO.getParentId(), child);
                        continue;
                    }

                    List<BdpDasCategoryDTO> child = typeTableMap.get(categoryDTO.getParentId());
                    child.add(categoryDTO);
                }
            }

            recursiveSetTable(categoryList, typeTableMap);

            return categoryList;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 数据开发工作台/数据计算，表管理时依据空间创建者过滤公共模型表
     * 注意：
     * 1、数据开发工作台，从公共模型导入到项目时使用；
     * 2、数据计算，从公共模型导入到项目时使用；
     *
     * @param projectId 项目空间ID
     * @param keyWords
     * @param secretLevel
     * @return
     */
    @Transactional(readOnly = true)
    public List<BdpDasCategoryDTO> findCategoryAndTableByProjectCreator(String projectId, String keyWords, String secretLevel) {
        if (StringUtils.isEmpty(projectId)) {
            throw new BusinessException("项目空间ID为空.");
        }

        // step1:获取项目空间创建者角色
        String creatorId = mapper.getCreatorByProjectId(projectId);
        if (StringUtils.isEmpty(creatorId)) {
            throw new BusinessException(String.format("项目空间[id=%s]创建者ID为空.", projectId));
        }
        List<String> roleIdList = commonService.getRoleListByUserId(creatorId);
        if (CollectionUtils.isEmpty(roleIdList)) {
            logger.warn(String.format("未查询到空间[id=%s]创建者[id=%s]的对应角色", projectId, creatorId));
            return Lists.newArrayList();
        }

        // step2:根据创建者角色，获取模型分类树
        List<BdpDasCategoryDTO> categoryList = findCategoryTreeByRole(roleIdList);

        // step3:获取模型表 从公共模型导入的
        List<String> wordSecretList = new ArrayList<>();
        if (StringUtils.isNotEmpty(secretLevel)) {
            wordSecretList.addAll(this.sysLookupClient.getSecretWordList(secretLevel));
        } else {
            wordSecretList = ThreadContextHelper.getWordSecretList();
        }
        List<BdpTableDTO> allTableList = bdpDasTableService.qureyTableListWithPerm(roleIdList,
                TableTypeEnum.TABLE_PHYSICAL.getCode(),
                "0",
                null,
                DataStateEnum.PUBLISHED.getCode(),
                keyWords,
                null,
                null,
                wordSecretList);
        if (CollectionUtils.isEmpty(allTableList)) {
            return categoryList;
        }

        // step4:过滤掉已导入的公共模型
        // 获取已导入的公共模型表
        List<BdpTableDTO> importedTableList = bdpDasTableService.selectListByProjectId(projectId);
        // 剔除已导入的公共模型表
        Map<String, BdpTableDTO> allTblMap =
                allTableList.stream().collect(Collectors.toMap(BdpTableDTO::getId, obj -> obj));
        for (BdpTableDTO importedTable : importedTableList) {
            if (importedTable == null) {
                continue;
            }
            if (StringUtils.isNotEmpty(importedTable.getId()) && allTblMap.containsKey(importedTable.getId())) {
                allTblMap.remove(importedTable.getId());
            }
        }
        if (allTblMap.size() <= 0) {
            return categoryList;
        }

        // step4:组装返回结果,模型挂载到分类树末级节点上
        List<BdpDasCategoryDTO> tmpCategoryList = Lists.newArrayList();
        for (BdpTableDTO dasTableDTO : allTblMap.values()) {
            BdpDasCategoryDTO tableDto = new BdpDasCategoryDTO();
            tableDto.setParentId(dasTableDTO.getTypeId());
            tableDto.setId(dasTableDTO.getId());
            tableDto.setName(dasTableDTO.getName());
            tableDto.setTableFlag(1);
            tableDto.setStoreStatus(dasTableDTO.getStoreStatus());
            tmpCategoryList.add(tableDto);
        }

        Map<String, List<BdpDasCategoryDTO>> typeTableMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(tmpCategoryList)) {
            for (BdpDasCategoryDTO categoryDTO : tmpCategoryList) {
                if (categoryDTO == null || StringUtils.isBlank(categoryDTO.getParentId())) {
                    continue;
                }

                if (!typeTableMap.containsKey(categoryDTO.getParentId())) {
                    List<BdpDasCategoryDTO> child = new ArrayList<>();
                    child.add(categoryDTO);
                    typeTableMap.put(categoryDTO.getParentId(), child);
                    continue;
                }

                List<BdpDasCategoryDTO> child = typeTableMap.get(categoryDTO.getParentId());
                child.add(categoryDTO);
            }
        }

        recursiveSetTable(categoryList, typeTableMap);

        return categoryList;
    }

    /**
     * 查询树结构（进行权限过滤）
     * 注意：
     * 1、数据建模，获取模型分类树
     *
     * @return
     */
    @Transactional(readOnly = true)
    public List<BdpDasCategoryDTO> findCategoryList() {
        // step1:获取角色列表、系统配置的授权角色
        List<String> roleIdList = this.commonService.getRoleListByUserId(ThreadContextHelper.getUserId());

        // step2:根据角色获取目录树
        return findCategoryTreeByRole(roleIdList);
    }

    /**
     * 判断分类名称是否重复（同一层级）
     *
     * @param categoryId
     * @param categoryName
     * @return
     */
    public Integer isSameName(String categoryId, String categoryName, String parentId) {
        Integer flag = 0;
        BdpDasCategoryDTO bdpDasCategoryDTO = new BdpDasCategoryDTO();
        bdpDasCategoryDTO.setParentId(parentId);
        bdpDasCategoryDTO.setName(categoryName);
        List<BdpDasCategoryDTO> list = selectList(bdpDasCategoryDTO);
        if (list != null && list.size() > 0) {
            if (StringUtils.isEmpty(categoryId)) {
                return 1;
            }
            for (BdpDasCategoryDTO dto : list) {
                if (!dto.getId().equals(categoryId)) {
                    flag = 1;
                    break;
                }
            }
        }
        return flag;
    }

    /**
     * 判断分类code是否重复
     *
     * @param categoryCode
     * @return
     */
    public Integer isSameCode(String categoryId, String categoryCode) {
        Integer flag = 0;
        BdpDasCategoryDTO bdpDasCategoryDTO = new BdpDasCategoryDTO();
        bdpDasCategoryDTO.setCode(categoryCode);
        List<BdpDasCategoryDTO> list = selectList(bdpDasCategoryDTO);
        if (list != null && list.size() > 0) {
            if (StringUtils.isEmpty(categoryId)) {
                return 1;
            }
            for (BdpDasCategoryDTO dto : list) {
                if (!dto.getId().equals(categoryId)) {
                    flag = 1;
                    break;
                }
            }
        }
        return flag;
    }

    /**
     * 获取最大排序
     *
     * @param categoryId
     * @return
     */
    @Transactional(readOnly = true)
    public Integer getMaxOrder(String categoryId) {
        Integer maxOrder = bdpDasCategoryDao.selectMaxOrder(categoryId);
        return (maxOrder / 10) * 10 + 10;
    }

    /**
     * 根据节点ID递归获取子节点列表（包括自身，仅包含具有查看、编辑权限的节点）
     *
     * @param parentNodeId 当前节点ID
     * @return
     */
    @Transactional(readOnly = true)
    public Map<String, Integer> getChildNodeMapWithPerm(String parentNodeId, List<String> roleIdList) {
        if (StringUtils.isEmpty(parentNodeId)) {
            return new HashMap<>();
        }

        // 获取分类树
        List<BdpDasCategoryDTO> categoryTree = findCategoryTreeByRole(roleIdList);

        // 获取指定父节点
        List<BdpDasCategoryDTO> resultNodeList = Lists.newArrayList();
        recursiveGetNodeById(parentNodeId, categoryTree, resultNodeList);
        if (CollectionUtils.isEmpty(resultNodeList)) {
            return new HashMap<>();
        }

        // 遍历获取子节点（包括自身）
        Map<String, Integer> childNodePermMap = new HashMap<>();
        recursiveGetChildNodePermMap(resultNodeList.get(0), childNodePermMap);

        return childNodePermMap;
    }

    /**
     * 根据节点ID递归获取子节点列表（包括自身，仅包含具有查看、数据查看权限的节点）
     *
     * @param parentNodeId 当前节点ID
     * @param roleIdList   角色列表
     * @return
     */
    @Transactional(readOnly = true)
    public Map<String, Integer> getChildNodePermListWithDataViewPerm(String parentNodeId, List<String> roleIdList) {
        if (StringUtils.isEmpty(parentNodeId)) {
            return new HashMap<>();
        }

        // 获取分类树(根据登录角色过滤)
        List<BdpDasCategoryDTO> allNodeList = findCategoryListOwnedDataViewPerm(roleIdList);

        // 获取指定父节点
        List<BdpDasCategoryDTO> resultNodeList = Lists.newArrayList();
        recursiveGetNodeById(parentNodeId, allNodeList, resultNodeList);
        if (CollectionUtils.isEmpty(resultNodeList)) {
            return new HashMap<>();
        }

        // 遍历获取子节点（包括自身）
        Map<String, Integer> childNodePermMap = new HashMap<>();
        recursiveGetChildNodePermMap(resultNodeList.get(0), childNodePermMap);

        return childNodePermMap;
    }

    /**
     * 根据分类节点构建模型分类树
     * 场景1：数据授权界面。根据授权角色+数据权限构建分类树
     * 场景2：模型授权界面，根据keyWords搜索分类树节点
     *
     * @param nodeIdList
     * @param keyWords
     * @return
     */
    @Transactional(readOnly = true)
    public List<BdpDasCategoryDTO> getCategoryTree(List<String> nodeIdList, String keyWords) {
        // step1:构建模型分类树
        List<BdpDasCategoryDTO> rootNodeList = new ArrayList<>();
        List<BdpDasCategoryDTO> allNodeList = getComleteNodeListInner(nodeIdList);// 获取完全树节点，未进行keyWords过滤
        if (StringUtils.isNotEmpty(keyWords)) {
            // 包含keyWords的节点集合
            List<BdpDasCategoryDTO> keyWordNodeList = allNodeList.stream()
                    .filter(item -> item.getName().contains(keyWords)).collect(Collectors.toList());
            //再次获取仅包含keyWords的完全树节点
            allNodeList = getComleteNodeListInner(keyWordNodeList.stream().map(BdpDasCategoryDTO::getId).collect(Collectors.toList()));
        }
        buildCategoryTree(allNodeList, rootNodeList, new HashMap<>());

        // step2:根节点特殊处理，保证任何角色都能看到根节点
        if (CollectionUtils.isEmpty(rootNodeList)) {
            BdpDasCategoryDTO rootNode = this.mapper.findCategoryRootNode();
            rootNodeList.add(rootNode);
        }

        return rootNodeList;
    }

    /**
     * 列举模型分类树（根据角色进行权限过滤，树形结构）
     *
     * @param roleIdList
     * @return
     */
    @Transactional(readOnly = true)
    public List<BdpDasCategoryDTO> findCategoryTreeByRole(List<String> roleIdList) {
        List<BdpDasCategoryDTO> rootNodeList = new ArrayList<>();
        if (CollectionUtils.isEmpty(roleIdList)) {
            return rootNodeList;
        }

        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
        // step1:获取所有节点
        List<BdpDasCategoryDTO> allNodeList = this.bdpDasCategoryDao.getCategoryListWithoutPerm(StatusEnums.RUNNING.getCode(), wordSecretList);
        /*BdpDasCategoryDTO parentNode = this.mapper.findCategoryRootNode();
        allNodeList.add(0,parentNode);*/
        // step2:根据角色获取权限列表(最大权限)
        List<CategoryPermDTO> permList = getFinalPermList(roleIdList);

        // step3:构建模型分类树
        buildCategoryTree(allNodeList, rootNodeList, new HashMap<>());

        // step4:设置分类节点权限值
        setNodeMaxPerm(rootNodeList, permList);

        // step5:根节点特殊处理，保证任何角色都能看到根节点
        if (CollectionUtils.isEmpty(rootNodeList)) {
            BdpDasCategoryDTO rootNode = this.mapper.findCategoryRootNode();
            rootNodeList.add(rootNode);
        }

        return rootNodeList;
    }

    /**
     * 数据授权时，获取未授权的模型列表（树结构，分类树仅关注数据查看权限）
     * 注意：
     * 1、提供给数据授权使用，数据授权时获取未授权的模型分类及模型（剔除已授权的模型）
     *
     * @param roleId
     * @param authedTableIdList
     * @return
     */
    @Transactional(readOnly = true)
    public List<BdpDasCategoryDTO> findUnauthedTableList(String roleId, List<String> authedTableIdList) {
        // step1:获取模型分类树
        List<BdpDasCategoryDTO> categoryList = findCategoryListOwnedDataViewPerm(Arrays.asList(roleId));
        if (CollectionUtils.isEmpty(categoryList)) {
            return Lists.newArrayList();
        }

        // step2:获取所有模型列表
        Page<BdpTableDTO> queryRet = bdpDasTableService.qureyTableListWithDataViewPerm(Arrays.asList(roleId),
                TableTypeEnum.TABLE_PHYSICAL.getCode(),
                "0",
                DataStateEnum.PUBLISHED.getCode(), null, null, null);
        if (queryRet == null || CollectionUtils.isEmpty(queryRet.getResult())) {
            return categoryList;
        }
        List<BdpTableDTO> allTableList = queryRet.getResult();

        // step3:剔除已授权的模型
        List<BdpDasCategoryDTO> unauthedTableList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(authedTableIdList)) {
            Set<String> authedTableIdSet = new HashSet<>(authedTableIdList);
            List<BdpTableDTO> delList = Lists.newArrayList();
            for (BdpTableDTO dasTableDTO : allTableList) {
                if (authedTableIdSet.contains(dasTableDTO.getId())) {
                    delList.add(dasTableDTO);
                }
            }
            allTableList.removeAll(delList);
        }

        for (BdpTableDTO dasTableDTO : allTableList) {
            BdpDasCategoryDTO tableDto = new BdpDasCategoryDTO();
            tableDto.setParentId(dasTableDTO.getTypeId());
            tableDto.setId(dasTableDTO.getId());
            tableDto.setName(dasTableDTO.getName());
            tableDto.setTableFlag(1);
            tableDto.setStoreStatus(dasTableDTO.getStoreStatus());
            unauthedTableList.add(tableDto);
        }

        // step4:模型挂载到分类树末级节点上
        Map<String, List<BdpDasCategoryDTO>> typeTableMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(unauthedTableList)) {
            for (BdpDasCategoryDTO categoryDTO : unauthedTableList) {
                if (categoryDTO == null || StringUtils.isBlank(categoryDTO.getParentId())) {
                    continue;
                }

                if (!typeTableMap.containsKey(categoryDTO.getParentId())) {
                    List<BdpDasCategoryDTO> child = new ArrayList<>();
                    child.add(categoryDTO);
                    typeTableMap.put(categoryDTO.getParentId(), child);
                    continue;
                }

                List<BdpDasCategoryDTO> child = typeTableMap.get(categoryDTO.getParentId());
                child.add(categoryDTO);
            }
        }

        recursiveSetTable(categoryList, typeTableMap);

        return categoryList;
    }

    /**
     * 查询树结构（进行权限过滤，仅关心是否具有数据查看权限）
     * 注意：
     * 1、数据查看，获取模型分类树
     *
     * @param roleIdList
     * @return
     */
    @Transactional(readOnly = true)
    public List<BdpDasCategoryDTO> findCategoryListOwnedDataViewPerm(List<String> roleIdList) {
        // step1:角色列表为空
        if (CollectionUtils.isEmpty(roleIdList)) {
            return new ArrayList<>();
        }

        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
        // step2:获取所有节点
        List<BdpDasCategoryDTO> allNodeList =
                this.bdpDasCategoryDao.getCategoryListWithoutPerm(StatusEnums.RUNNING.getCode(), wordSecretList);

        // step3:根据角色获取权限列表(最大权限)
        List<CategoryPermDTO> permList = getFinalDataViewPermList(roleIdList);

        // step4:构建模型分类树
        List<BdpDasCategoryDTO> rootNodeList = new ArrayList<>();
        buildCategoryTree(allNodeList, rootNodeList, new HashMap<>());

        // step5:根节点特殊处理，保证任何角色都能看到根节点
        if (CollectionUtils.isEmpty(rootNodeList)) {
            BdpDasCategoryDTO rootNode = this.mapper.findCategoryRootNode();
            rootNodeList.add(rootNode);
        }

        // step6:设置分类节点权限值
        setNodeMaxPerm(rootNodeList, permList);

        return rootNodeList;
    }

    /**
     * 获取最大的数据查看权限
     *
     * @param roleIdList
     * @return
     */
    public List<CategoryPermDTO> getFinalDataViewPermList(List<String> roleIdList) {
        Map<String, CategoryPermDTO> permDTOMap = new HashMap<>();
        List<CategoryPermDTO> tmpPermList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(roleIdList)) {
            // 获取所有角色对应的权限
            tmpPermList = this.commonService.getCategoryDataViewPermListByRoles(roleIdList);

            // 遍历权限列表，设置每个节点的最大权限
            for (CategoryPermDTO dto : tmpPermList) {
                String nodeId = dto.getNodeId();
                CategoryPermDTO exisitDto = permDTOMap.get(nodeId);
                if (exisitDto == null) {
                    permDTOMap.put(nodeId, dto);
                    continue;
                }

                if (exisitDto.getAction() < dto.getAction()) {
                    exisitDto.setAction(dto.getAction());
                }
            }
        }

        return new ArrayList<>(permDTOMap.values());
    }

    /**
     * 设置子节点信息
     *
     * @param list
     * @param map
     */
    private void listConvert(List<BdpDasCategoryDTO> list, Map<String, List<BdpDasCategoryDTO>> map) {
        for (BdpDasCategoryDTO bdpDasCategoryDTO : list) {
            List<BdpDasCategoryDTO> categoryDTOS = map.get(bdpDasCategoryDTO.getId());
            if (CollectionUtils.isNotEmpty(categoryDTOS)) {
                listConvert(categoryDTOS, map);
                bdpDasCategoryDTO.setChildren(categoryDTOS);
            } else {
                bdpDasCategoryDTO.setChildren(null);
            }
        }
    }

    /**
     * 递归设置模型分类节点下的模型列表
     *
     * @param categoryList
     * @param typeTableMap
     */
    private void recursiveSetTable(List<BdpDasCategoryDTO> categoryList, Map<String, List<BdpDasCategoryDTO>> typeTableMap) {
        if (CollectionUtils.isEmpty(categoryList)) {
            return;
        }

        for (BdpDasCategoryDTO categoryDTO : categoryList) {
            if (categoryDTO.getLeaf() == 1) {
                List<BdpDasCategoryDTO> tableList = typeTableMap.get(categoryDTO.getId());
                if (CollectionUtils.isNotEmpty(tableList)) {
                    categoryDTO.setChildren(tableList);
                }
            } else {
                recursiveSetTable(categoryDTO.getChildren(), typeTableMap);
            }
        }
    }

    /**
     * 普通角色获取最终权限列表
     *
     * @param roleIdList
     * @return
     */
    public List<CategoryPermDTO> getFinalPermList(List<String> roleIdList) {
        Map<String, CategoryPermDTO> permDTOMap = new HashMap<>();
        List<CategoryPermDTO> tmpPermList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(roleIdList)) {
            // 获取所有角色对应的权限
            tmpPermList = this.commonService.getCategoryPermListByRoles(roleIdList);

            // 遍历权限列表，设置每个节点的最大权限
            for (CategoryPermDTO dto : tmpPermList) {
                String nodeId = dto.getNodeId();
                CategoryPermDTO exisitDto = permDTOMap.get(nodeId);
                if (exisitDto == null) {
                    permDTOMap.put(nodeId, dto);
                    continue;
                }

                if (exisitDto.getAction() < dto.getAction()) {
                    exisitDto.setAction(dto.getAction());
                }
            }
        }

        return new ArrayList<>(permDTOMap.values());
    }

    /**
     * 普通角色获取完全节点列表
     *
     * @param nodeIdList
     * @return
     */
    private List<BdpDasCategoryDTO> getComleteNodeListInner(List<String> nodeIdList) {
        if (CollectionUtils.isEmpty(nodeIdList)) {
            return Lists.newArrayList();
        }

        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
        // step1:获取所有分类节点
        List<BdpDasCategoryDTO> allNodeList =
                this.bdpDasCategoryDao.getCategoryListWithoutPerm(StatusEnums.RUNNING.getCode(), wordSecretList);

        // step2:生成Map<节点ID, 节点>映射关系
        Map<String, BdpDasCategoryDTO> allNodeMap = allNodeList.stream()
                .collect(Collectors.toMap(BdpDasCategoryDTO::getId, item -> item));

        // step3:构建完全树
        Set<BdpDasCategoryDTO> completeNodeSet = new HashSet<>();
        for (String nodeId : nodeIdList) {
            BdpDasCategoryDTO currNode = allNodeMap.get(nodeId);
            while (currNode != null) {
                if (!completeNodeSet.contains(currNode)) {
                    completeNodeSet.add(currNode);
                }

                currNode = allNodeMap.get(currNode.getParentId());
            }
        }

        return new ArrayList<>(completeNodeSet);
    }

    /**
     * 设置每个节点的权限
     * 注意：
     * 1、场景1：授权界面中，授权角色根据roleId获取授予的权限
     *
     * @param allNodeList
     * @param permList
     */
    private void setNodeGrantedPerm(List<BdpDasCategoryDTO> allNodeList, List<CategoryPermDTO> permList) {
        // step1:生成Map<节点ID, 节点>映射关系
        Map<String, BdpDasCategoryDTO> allNodeMap = allNodeList.stream()
                .collect(Collectors.toMap(BdpDasCategoryDTO::getId, item -> item));

        // step2:遍历分类节点，设置其拥有的最大权限
        if (CollectionUtils.isEmpty(permList)) {
            return;
        }

        for (CategoryPermDTO permDTO : permList) {
            if (permDTO == null) {
                continue;
            }

            BdpDasCategoryDTO categoryDTO = allNodeMap.get(permDTO.getNodeId());
            if (categoryDTO != null) {
                categoryDTO.setAction(permDTO.getAction());
                List<Integer> actionList = categoryDTO.getActionList();
                if (CollectionUtils.isEmpty(actionList)) {
                    actionList = new ArrayList<>();
                    categoryDTO.setActionList(actionList);
                }
                actionList.add(permDTO.getAction());
            }
        }
    }

    /**
     * 设置每个节点的权限
     * 注意：
     * 1、场景1：管理界面中，设置节点的最大权限
     *
     * @param allNodeList
     * @param permList
     */
    private void setNodeMaxPerm(List<BdpDasCategoryDTO> allNodeList, List<CategoryPermDTO> permList) {
        // step1:生成Map<节点ID,权限>映射关系
        Map<String, CategoryPermDTO> permMap = permList.stream().collect(Collectors.toMap(CategoryPermDTO::getNodeId, item -> item));

        // step2:递归设置节点权限
        recuriveSetNodePerm(allNodeList, permMap, null);

        // step3:递归删除无权限无子目录的节点
        recuriveDelNonePermNode(allNodeList);
    }

    /**
     * 递归设置节点权限
     *
     * @param nodeList
     * @param permMap
     * @param ancestorAction
     */
    private void recuriveSetNodePerm(List<BdpDasCategoryDTO> nodeList, Map<String, CategoryPermDTO> permMap, Integer ancestorAction) {
        if (CollectionUtils.isEmpty(nodeList)) {
            return;
        }
        if (permMap == null || permMap.size() <= 0) {
            return;
        }

        Iterator<BdpDasCategoryDTO> it = nodeList.iterator();
        while (it.hasNext()) {
            BdpDasCategoryDTO dto = it.next();
            if (dto == null || StringUtils.isEmpty(dto.getId())) {
                continue;
            }

            // 获取当前节点权限
            CategoryPermDTO permDTO = permMap.get(dto.getId());

            // 设置当前节点权限
            Integer currNodeAction = calcCurrNodeAction(permDTO, ancestorAction);
            dto.setAction(currNodeAction);
            setActionList(dto, currNodeAction);

            // 当前节点有子目录，设置子目录权限
            List<BdpDasCategoryDTO> childList = dto.getChildren();
            if (CollectionUtils.isNotEmpty(childList)) {
                recuriveSetNodePerm(childList, permMap, currNodeAction);
            }
        }
    }

    /**
     * 递归删除指定节点（无子目录、无权限）
     *
     * @param nodeList
     */
    private void recuriveDelNonePermNode(List<BdpDasCategoryDTO> nodeList) {
        if (CollectionUtils.isEmpty(nodeList)) {
            return;
        }

        Iterator<BdpDasCategoryDTO> it = nodeList.iterator();
        while (it.hasNext()) {
            BdpDasCategoryDTO dto = it.next();
            if (dto == null) {
                continue;
            }

            List<BdpDasCategoryDTO> childList = dto.getChildren();
            if (CollectionUtils.isNotEmpty(childList)) {
                recuriveDelNonePermNode(childList);
            }

            // 获取当前节点权限、子节点列表
            Integer action = dto.getAction();
            if (action == null) {
                // 根节点不删除，非根节点&&无权限&&无子节点要删除
                if (!dto.getParentId().equals("-1") && CollectionUtils.isEmpty(childList)) {
                    it.remove();
                }
            }
        }
    }

    /**
     * 计算当前节点权限
     *
     * @param currNodePerm
     * @param ancestorAction
     * @return
     */
    private Integer calcCurrNodeAction(CategoryPermDTO currNodePerm, Integer ancestorAction) {
        if (currNodePerm == null || currNodePerm.getAction() == null) {
            return ancestorAction;
        }
        if (ancestorAction == null) {
            return currNodePerm.getAction();
        }

        Integer currNodeAction = currNodePerm.getAction();
        if (ancestorAction < currNodeAction) {
            return currNodePerm.getAction();
        }

        return ancestorAction;
    }

    /**
     * 设置权限列表
     *
     * @param dto
     * @param action
     */
    private void setActionList(BdpDasCategoryDTO dto, Integer action) {
        List<Integer> actionList = new ArrayList<>();
        dto.setActionList(actionList);

        if (action == null) {
            return;
        }

        if (action == 0) {
            actionList.add(0);
        } else if (action == 1) {
            actionList.add(0);
            actionList.add(1);
        } else if (action == 2) {
            actionList.add(0);
            actionList.add(2);
        }
    }

    /**
     * 内部方法，获取修改的dto对象
     *
     * @param
     * @return
     */
    private BdpDasCategoryDTO getUpdateDto(BdpDasCategoryDTO bdpDasCategoryDTO) {
        BdpDasCategoryDTO oldDTO = selectByPrimaryKey(bdpDasCategoryDTO.getId());
        if (oldDTO == null) {
            throw new BusinessException("数据不存在");
        }

        // 校验标准名称唯一性
        if (!bdpDasCategoryDTO.getName().equals(oldDTO.getName())) {
            checkNameUnique(bdpDasCategoryDTO);
        }

        // 校验标准编码唯一性
        if (!bdpDasCategoryDTO.getCode().equals(oldDTO.getCode())) {
            checkCodeUnique(bdpDasCategoryDTO);
        }

        //记录日志
        BdpLogUtil.log4Update(bdpDasCategoryDTO, oldDTO);

        oldDTO.setCode(bdpDasCategoryDTO.getCode());
        oldDTO.setName(bdpDasCategoryDTO.getName());
        oldDTO.setOrderBy(bdpDasCategoryDTO.getOrderBy());
        oldDTO.setRemark(bdpDasCategoryDTO.getRemark());
        if (StringUtils.isNotBlank(bdpDasCategoryDTO.getParentId())) {
            oldDTO.setParentId(bdpDasCategoryDTO.getParentId());
        }
        return oldDTO;
    }

    /**
     * 构建模型分类树
     *
     * @param allNodeList  入参，所有节点列表
     * @param rootNodeList 入参/返回值，根节点列表
     * @param childNodeMap 入参/返回值，Map<父节点ID,子节点列表>映射关系
     */
    private void buildCategoryTree(List<BdpDasCategoryDTO> allNodeList,
                                   List<BdpDasCategoryDTO> rootNodeList,
                                   Map<String, List<BdpDasCategoryDTO>> childNodeMap) {
        // 获取Map<父节点ID，List<子节点>>映射关系
        getChildNodeMap("-1", allNodeList, rootNodeList, childNodeMap);

        // 设置子节点列表
        listConvert(rootNodeList, childNodeMap);
    }

    /**
     * 获取Map<父节点ID，List<子节点>>映射关系
     *
     * @param rootNodeId
     * @param allNodeList
     * @param rootNodeList
     * @param childNodeMap
     * @return
     */
    private void getChildNodeMap(String rootNodeId, List<BdpDasCategoryDTO> allNodeList,
                                 List<BdpDasCategoryDTO> rootNodeList,
                                 Map<String, List<BdpDasCategoryDTO>> childNodeMap) {
        if (CollectionUtils.isEmpty(allNodeList)) {
            return;
        }

        /*allNodeList = allNodeList.stream()
                .sorted(Comparator.comparing(BdpDasCategoryDTO::getOrderBy, Comparator.nullsLast(Integer::compareTo)))
                .collect(Collectors.toList());*/

        for (BdpDasCategoryDTO categoryDTO : allNodeList) {
            // root节点
            if (rootNodeId.equals(categoryDTO.getParentId())) {
                rootNodeList.add(categoryDTO);
                continue;
            }

            // 非初次，加入父节点的子节点列表中
            if (childNodeMap.containsKey(categoryDTO.getParentId())) {
                childNodeMap.get(categoryDTO.getParentId()).add(categoryDTO);
                continue;
            }

            // 初次，创建&&加入子节点列表
            List<BdpDasCategoryDTO> childNodeList = Lists.newArrayList();
            childNodeList.add(categoryDTO);
            childNodeMap.put(categoryDTO.getParentId(), childNodeList);
        }
    }

    /**
     * 递归获取指定节点
     *
     * @param nodeId
     * @param allNodeList
     * @param resultNodeList
     * @return
     */
    private void recursiveGetNodeById(String nodeId, List<BdpDasCategoryDTO> allNodeList,
                                      List<BdpDasCategoryDTO> resultNodeList) {
        if (CollectionUtils.isEmpty(allNodeList)) {
            return;
        }

        for (BdpDasCategoryDTO dto : allNodeList) {
            if (dto == null || StringUtils.isEmpty(dto.getId())) {
                continue;
            }
            if (dto.getId().equals(nodeId)) {
                resultNodeList.add(dto);
                return;
            }
            if (dto.getLeaf() == 0) {
                recursiveGetNodeById(nodeId, dto.getChildren(), resultNodeList);
            }
        }
    }

    /**
     * 递归获取所有子节点ID列表
     *
     * @param parentNode
     * @param resultNodeIdList
     */
    private void recursiveGetChildNodeIdList(BdpDasCategoryDTO parentNode, List<String> resultNodeIdList) {
        if (parentNode == null) {
            return;
        }

        if (parentNode.getAction() != null) {
            resultNodeIdList.add(parentNode.getId());
        }

        if (CollectionUtils.isEmpty(parentNode.getChildren())) {
            return;
        }

        for (BdpDasCategoryDTO currNode : parentNode.getChildren()) {
            recursiveGetChildNodeIdList(currNode, resultNodeIdList);
        }
    }

    /**
     * 递归获取所有子节点权限列表
     *
     * @param parentNode
     * @param resultMap
     */
    private void recursiveGetChildNodePermMap(BdpDasCategoryDTO parentNode, Map<String, Integer> resultMap) {
        if (parentNode == null) {
            return;
        }

        if (parentNode.getAction() != null) {
            resultMap.put(parentNode.getId(), parentNode.getAction());
        }

        if (CollectionUtils.isEmpty(parentNode.getChildren())) {
            return;
        }

        for (BdpDasCategoryDTO currNode : parentNode.getChildren()) {
            recursiveGetChildNodePermMap(currNode, resultMap);
        }
    }

    /**
     * @param categoryName
     * @param parentId
     * @param categoryIds  所属权限可以查询的分类
     * @return
     */
    public BdpDasCategoryDTO selectListByAuth(String categoryName, String parentId, List<String> categoryIds) {
        return this.mapper.selectListByAuth(categoryName, parentId, categoryIds);
    }

    @Transactional(readOnly = true)
    public List<BdpDasCategoryDTO> findCategorys() {
        try {
            List<String> roleIdList = this.commonService.getRoleListByUserId(ThreadContextHelper.getUserId());
            List<BdpDasCategoryDTO> categoryList = findCategoryListOwnedDataViewPerm(roleIdList);

            return categoryList;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }


    public void updateStatus(String id, Integer status, Integer lowerNode) {
        CheckParaUtils.checkStringValidity(id, logger, "没有传入待启用/停用的ID");

        BdpDasCategoryDTO categoryDTO = this.selectByPrimaryKey(id);
        CheckParaUtils.checkDbObjectValidity(categoryDTO, logger, String.format("没有查到数据，请确保id:%s的主题是否存在", id));

        //获取相关上级节点
        List<String> ids = Lists.newArrayList();
        if(status == StatusEnums.RUNNING.getCode()) {
            getParentIds(id, ids);
        }
        //当前节点id
        ids.add(id);
        //获取自己节点id
        if (lowerNode == 1 && categoryDTO.getLeaf() == 0) {
            BdpDasCategoryDTO query = new BdpDasCategoryDTO();
            query.setParentId(id);
            List<BdpDasCategoryDTO> child = this.selectList(query);
            List<String> childIds = Lists.newArrayList();
            getChildIds(child, childIds);
            ids.addAll(childIds);
        }

        String logTitle = "";
        if (status == 0) {
            logTitle = "停用主题：【";
        } else {
            logTitle = "启用主题：【";
        }
        logTitle += categoryDTO.getName() + "】";
        BdpLogUtil.log("主题模块", logTitle, PlatformConstant.OpType.update);
        this.mapper.updateStatus(ids, status);
    }

    //获取当前节点的所有启用状态的下级节点id
    private void getChildIds(List<BdpDasCategoryDTO> childs, List<String> childIds) {
        if (CollectionUtils.isNotEmpty(childs)) {
            for (BdpDasCategoryDTO bdpDasCategoryDTO : childs) {
                childIds.add(bdpDasCategoryDTO.getId());
                if (bdpDasCategoryDTO.getLeaf() == 0) {
                    BdpDasCategoryDTO query = new BdpDasCategoryDTO();
                    query.setParentId(bdpDasCategoryDTO.getId());
                    //query.setStatus(StatusEnums.RUNNING.getCode());
                    List<BdpDasCategoryDTO> child = this.selectList(query);
                    getChildIds(child, childIds);
                }
            }
        }
    }

    //获取当前节点的上级节点id
    private void getParentIds(String id, List<String> parentIds) {
        if ("0".equals(id)) {
            return;
        } else {
            BdpDasCategoryDTO categoryDTO = this.selectByPrimaryKey(id);
            parentIds.add(categoryDTO.getParentId());
            getParentIds(categoryDTO.getParentId(), parentIds);
        }
    }

    /**
     * 根据主题id查询下一级主题
     *
     * @param categoryId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public QueryRespBean<BdpDasCategoryDTO> findCategoryDataList(String categoryId, String keyWords, Integer pageNo,
                                                                 Integer pageSize) {
        QueryRespBean<BdpDasCategoryDTO> queryRespBean = new QueryRespBean<>();
        com.github.pagehelper.PageHelper.startPage(pageNo, pageSize);

        Page<BdpDasCategoryDTO> page = this.mapper.getPageList(categoryId, keyWords);
        queryRespBean.setResult(page);
        BdpLogUtil.log4Query(queryRespBean);
        return queryRespBean;
    }

    /**
     * 根据id查询子节点id（无权限）
     *
     * @param categoryId
     * @return
     */
    public List<String> getChildTypeIds(String categoryId) {
        List<BdpDasCategoryDTO> categoryDTOList = Lists.newArrayList();
        List<String> categoryIds = Lists.newArrayList();
        BdpDasCategoryDTO categoryDTO = this.selectByPrimaryKey(categoryId);
        categoryDTOList.add(categoryDTO);
        getChildIds(categoryDTOList, categoryIds);
        return categoryIds;
    }

    /**
     * 校验名称唯一性
     *
     * @param categoryDTO 检测对象
     */
    private void checkNameUnique(BdpDasCategoryDTO categoryDTO) {
        if (categoryDTO != null) {
            if (StringUtils.isEmpty(categoryDTO.getName())) {
                throw new BusinessException("名称不能为空");
            }

            BdpDasCategoryDTO paramName = new BdpDasCategoryDTO();
            paramName.setName(categoryDTO.getName());
            paramName.setParentId(categoryDTO.getParentId());
            if (this.selectCount(paramName) > 0) {
                throw new BusinessException("名称[" + categoryDTO.getName() + "]已存在");
            }
        }
    }

    /**
     * 校验名称和代码唯一性
     *
     * @param categoryDTO 检测对象
     */
    private void checkCodeUnique(BdpDasCategoryDTO categoryDTO) {
        if (categoryDTO != null) {
            if (StringUtils.isEmpty(categoryDTO.getCode())) {
                throw new BusinessException("代码不能为空");
            }

            BdpDasCategoryDTO paramCode = new BdpDasCategoryDTO();
            paramCode.setCode(categoryDTO.getCode());
            //paramCode.setParentId(categoryDTO.getParentId());
            if (this.selectCount(paramCode) > 0) {
                throw new BusinessException("编码[" + categoryDTO.getCode() + "]已存在");
            }
        }
    }

    public BdpDasCategoryDTO queryById(String id) {
        BdpDasCategoryDTO categoryDTO = this.mapper.getCategoryById(id);
        CheckParaUtils.checkDbObjectValidity(categoryDTO, logger,
                String.format("没有查到数据，请确保id:%s的数据是否存在", id));

        return categoryDTO;
    }

    public List<BdpDasCategoryDTO> findCategoryTree() {
        List<BdpDasCategoryDTO> rootNodeList = new ArrayList<>();
        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
        // step1:获取所有节点
        List<BdpDasCategoryDTO> allNodeList = this.bdpDasCategoryDao.getCategoryListWithoutPerm(null, wordSecretList);
        //BdpDasCategoryDTO parentNode = this.mapper.findCategoryRootNode();
        //allNodeList.add(0,parentNode);

        // step2:构建模型分类树
        buildCategoryTree(allNodeList, rootNodeList, new HashMap<>());

        // step3:根节点特殊处理，保证任何角色都能看到根节点
        if (CollectionUtils.isEmpty(rootNodeList)) {
            BdpDasCategoryDTO rootNode = this.mapper.findCategoryRootNode();
            rootNodeList.add(rootNode);
        }
        return rootNodeList;
    }

    /**
     * 获取无权限启用状态主题树
     * @return
     */
    public List<BdpDasCategoryDTO> findCategoryTreeByStatus() {
        List<BdpDasCategoryDTO> rootNodeList = new ArrayList<>();

        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
        // step1:获取所有节点
        List<BdpDasCategoryDTO> allNodeList = this.bdpDasCategoryDao.getCategoryListWithoutPerm(StatusEnums.RUNNING.getCode(), wordSecretList);
        /*BdpDasCategoryDTO parentNode = this.mapper.findCategoryRootNode();
        allNodeList.add(0,parentNode);*/
        // step2:构建模型分类树
        buildCategoryTree(allNodeList, rootNodeList, new HashMap<>());

        // step3:根节点特殊处理，保证任何角色都能看到根节点
        if (CollectionUtils.isEmpty(rootNodeList)) {
            BdpDasCategoryDTO rootNode = this.mapper.findCategoryRootNode();
            rootNodeList.add(rootNode);
        }
        return rootNodeList;
    }

    public BdpDasCategoryDTO selectTopCategory() {
        return this.mapper.findCategoryRootNode();
    }


    public List<BdpDasCategoryDTO> findCategoryAndTable(String keyWords) {
        List<String> roleIdList = commonService.getRoleListByUserId(ThreadContextHelper.getUserId());
        if (CollectionUtils.isEmpty(roleIdList)) {
            logger.warn(String.format("未查询到用户的对应角色"));
            return Lists.newArrayList();
        }

        // step2:根据创建者角色，获取模型分类树
        List<BdpDasCategoryDTO> categoryList = findCategoryTreeByRole(roleIdList);

        // step3:获取模型表 从公共模型导入的
        List<BdpTableDTO> allTableList = bdpDasTableService.qureyTableListWithPerm(roleIdList,
                TableTypeEnum.TABLE_LOGIC.getCode(), "0",
                null, DataStateEnum.PUBLISHED.getCode(),
                keyWords, null, null, null);
        if (CollectionUtils.isEmpty(allTableList)) {
            return categoryList;
        }

        Map<String, BdpTableDTO> allTblMap =
                allTableList.stream().collect(Collectors.toMap(BdpTableDTO::getId, obj -> obj));
        if (allTblMap.size() <= 0) {
            return categoryList;
        }

        // step4:组装返回结果,模型挂载到分类树末级节点上
        List<BdpDasCategoryDTO> tmpCategoryList = Lists.newArrayList();
        for (BdpTableDTO dasTableDTO : allTblMap.values()) {
            BdpDasCategoryDTO tableDto = new BdpDasCategoryDTO();
            tableDto.setParentId(dasTableDTO.getTypeId());
            tableDto.setId(dasTableDTO.getId());
            tableDto.setName(dasTableDTO.getName());
            tableDto.setTableFlag(1);
            tableDto.setStoreStatus(dasTableDTO.getStoreStatus());
            tmpCategoryList.add(tableDto);
        }

        Map<String, List<BdpDasCategoryDTO>> typeTableMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(tmpCategoryList)) {
            for (BdpDasCategoryDTO categoryDTO : tmpCategoryList) {
                if (categoryDTO == null || StringUtils.isBlank(categoryDTO.getParentId())) {
                    continue;
                }

                if (!typeTableMap.containsKey(categoryDTO.getParentId())) {
                    List<BdpDasCategoryDTO> child = new ArrayList<>();
                    child.add(categoryDTO);
                    typeTableMap.put(categoryDTO.getParentId(), child);
                    continue;
                }

                List<BdpDasCategoryDTO> child = typeTableMap.get(categoryDTO.getParentId());
                child.add(categoryDTO);
            }
        }

        recursiveSetTable(categoryList, typeTableMap);

        return categoryList;
    }
}
